home *** CD-ROM | disk | FTP | other *** search
/ Pascal Super Library / Pascal Super Library (CW International)(1997).bin / XMS_UTL / XMSLI202 / XMSLIB.PAS < prev   
Pascal/Delphi Source File  |  1994-03-17  |  24KB  |  721 lines

  1. Unit XMSLib;
  2. { Copyright (c) 1994 by Andrew Eigus            Fido Net: 2:5100/20.12 }
  3. { XMS Interface V2.02 for Turbo Pascal version 7.0 }
  4.  
  5. (*
  6.   Description of XMS:
  7.     XMS: eXtended Memory Specification
  8.     XMS gives access to extended memory and noncontiguous/nonEMS
  9.     memory above 640K
  10.     UMB: Upper Memory Block
  11.     HMA: High Memory Area
  12.  
  13.   Material used:
  14.     C and ASM source of XMS Library (c) by Michael Graff,
  15.     eXtended Memory Specification unit source (c) by Yuval Tal,
  16.     Interrupt List V1.02 (WindowBook) (c) 1984-90 Box Company, Inc.
  17.   Goals:
  18.     All functions except GetErrorMsg written on inline assembler. That makes
  19.     library to work faster and to be small!
  20.     Whenever it's possible, error-handling checks are performed. However,
  21.     that doesn't mean you won't have any errors using this library.
  22.  
  23.   DISCLAIMER: This software provided 'as-is' and doesn't guarantee safety
  24.               of your system after using it!
  25.   This source may be freely distributed for non-commercial, non-business,
  26.   and non-governmental uses, provided this notice is attached with it.
  27. *)
  28.  
  29. interface
  30.  
  31. (* TYPES, CONSTS, VARS -----------------------------------------------------*)
  32.  
  33. const
  34.  
  35.   { XMS function numbers }
  36.  
  37.   XGetVersion    = $00;
  38.   XRequestHMA    = $01;
  39.   XReleaseHMA    = $02;
  40.   XGlobalE20     = $03;
  41.   XGlobalD20     = $04;
  42.   XLocalE20      = $05;
  43.   XLocalD20      = $06;
  44.   XQuery20       = $07;
  45.   XGetMemSize    = $08;
  46.   XAllocEMB      = $09;
  47.   XFreeEMB       = $0A;
  48.   XMoveEMB       = $0B;
  49.   XLockEMB       = $0C;
  50.   XUnlockEMB     = $0D;
  51.   XGetHandleInfo = $0E;
  52.   XReallocEMB    = $0F;
  53.   XRequestUMB    = $10;
  54.   XReleaseUMB    = $11;
  55.  
  56.   { XMS_GetVersion parameters }
  57.  
  58.   XMS = True;  { Get XMS version }
  59.   XMM = False; { Get XMM version }
  60.  
  61.   { XMS functions return codes }
  62.  
  63.   xmsrOk            = $00; { Function successful }
  64.   xmsrNotInitd      = $01; { XMS driver not initialized by XMS_Setup }
  65.   xmsrBadFunction   = $80; { Function not implemented }
  66.   xmsrVDiskDetected = $81; { VDisk was detected }
  67.   xmsrA20Error      = $82; { An A20 error occurred }
  68.   xmsrDriverError   = $8E; { A general driver error }
  69.   xmsrUnrecError    = $8F; { Unrecoverable driver error }
  70.   xmsrNoHMA         = $90; { HMA does not exist }
  71.   xmsrHMAInUse      = $91; { HMA is already in use }
  72.   xmsrHMAMinError   = $92; { HMAMIN parameter is too large }
  73.   xmsrHMANotAlloc   = $93; { HMA is not allocated }
  74.   xmsrA20Enabled    = $94; { A20 line still enabled }
  75.   xmsrNoMoreMem     = $A0; { All extended memory is allocated }
  76.   xmsrNoMoreHandles = $A1; { All available XMS handles are allocated }
  77.   xmsrBadHandle     = $A2; { Invalid handle }
  78.   xmsrBadSourceH    = $A3; { Source handle is invalid }
  79.   xmsrBadSourceO    = $A4; { Source offset is invalid }
  80.   xmsrBadDestH      = $A5; { Destination handle is invalid }
  81.   xmsrBadDestO      = $A6; { Destination offset is invalid }
  82.   xmsrBadLength     = $A7; { Length (size) is invalid }
  83.   xmsrBadOverlap    = $A8; { Move has an invalid overlap }
  84.   xmsrParityError   = $A9; { Parity error occurred }
  85.   xmsrBlkNotLocked  = $AA; { Block is not locked }
  86.   xmsrBlkLocked     = $AB; { Block is locked }
  87.   xmsrBlkLCOverflow = $AC; { Block lock count overflowed }
  88.   xmsrLockFailed    = $AD; { Lock failed }
  89.   xmsrSmallerUMB    = $B0; { Only a smaller UMB is available }
  90.   xmsrNoUMB         = $B1; { No UMB's are available }
  91.   xmsrBadUMBSegment = $B2; { UMB segment number is invalid }
  92.  
  93. type
  94.   THandle = Word; { Memory block handle type }
  95.  
  96. var
  97.   XMSResult : byte; { Returns the status of the last XMS operation performed }
  98.  
  99. (* FUNCTIONS -------------------------------------------------------------- *)
  100.  
  101. function XMS_Setup : boolean;
  102. { This function returns True is the extended memory manager device driver
  103.   is installed in memory and active. True if installed, False if not
  104.   installed. You should call this function first, before any other are
  105.   called so it will setup memory manager for use with your program }
  106.  
  107. function XMS_GetVersion(OfWhat : boolean) : word;
  108. { This function returns eighter the version of the extended memory
  109.   specifications version, or the version of the extended memory manager
  110.   device driver version, depends on what you're using as an OfWhat
  111.   parameter (see XMS_GetVersion parameters in const section of the unit).
  112.   The result's low byte is the major version number, and the high byte is
  113.   the minor version number }
  114.  
  115. function XMS_HMAAvail : boolean;
  116. { This function obtains the status of the high memory area (HMA).
  117.   If the result is true, HMA exists. If the result is False no HMA exists }
  118.  
  119. function XMS_AllocHMA(Size : word) : byte;
  120. { This function allocates high memory area (HMA). Size contains the the
  121.   bytes which are needed. The maximum HMA allocation is 65520 bytes.
  122.   The base address of the HMA is FFFF:0010h. If an application fails
  123.   to release the HMA before it terminates, the HMA becomes unavailable
  124.   to the other programs until the system is restarted. Function returns
  125.   zero (xmsrOk) if the call was successful, or one of the xmsr-error codes
  126.   if the call has failed }
  127.  
  128. function XMS_FreeHMA : byte;
  129. { This function releases the high memory area (HMA) and returns zero if
  130.   the call was successful, or one of the xmsr-error codes if the call has
  131.   failed }
  132.  
  133. function XMS_GlobalEnableA20 : byte;
  134. { This function enables the A20 line and should only be used by programs
  135.   that have successfully allocated the HMA. The result is zero if the
  136.   call was successful, otherwise, the result is one of the (xmsr)
  137.   return values }
  138.  
  139. function XMS_GlobalDisableA20 : byte;
  140. { This function disables the A20 line and should only be used by programs
  141.   that do not own the HMA. The result is zero if the call was successful,
  142.   otherwise, the result is one of the (xmsr) return values }
  143.  
  144. function XMS_LocalEnableA20 : byte;
  145. { This function enables the A20 line and should only be used by programs
  146.   that have successfully allocated the HMA. The result is zero if the call
  147.   was successful, otherwise, the result is one of the (xmsr) return values }
  148.  
  149. function XMS_LocalDisableA20 : byte;
  150. { This function disables the A20 line and should only be used by programs
  151.   that do not own the HMA. The A20 line should be disabled before the program
  152.   releases control of the system. The result is zero if the call was
  153.   successful, otherwise, the result is one of the (xmsr) return values }
  154.  
  155. function XMS_QueryA20 : boolean;
  156. { This function returns the status of the A20 address line. If the result is
  157.   True then the A20 line is enabled. If False, it is disabled }
  158.  
  159. function XMS_MemAvail : word;
  160. { This function returns the total free extended memory in kilo-bytes }
  161.  
  162. function XMS_MaxAvail : word;
  163. { This function returns the largest free extended memory block in kilo-bytes }
  164.  
  165. function XMS_AllocEMB(Size : word) : THandle;
  166. { This function allocates extended memory block (EMB). Size defines the size
  167.   of the requested block in kilo-bytes. Function returns a handle number
  168.   which is used by the other EMB commands to refer to this block. If the call
  169.   to this function was unsuccessful, zero is returned instead of the handle
  170.   number and (xmsr) error code is stored in XMSResult variable }
  171.  
  172. function XMS_ReallocEMB(Handle : THandle; Size : word) : byte;
  173. { This function reallocates EMB. Handle is a handle number which was given
  174.   by XMS_AllocEMB. Size defines a new size of the requested block in
  175.   kilo-bytes. Function returns zero if the call was successful, or
  176.   a (xmsr) error code if it failed }
  177.  
  178. function XMS_FreeEMB(Handle : THandle) : byte;
  179. { This function releases allocated extended memory. Handle is a handle number
  180.   which was given by XMS_AllocEMB. Note: If a program fails to release its
  181.   extended memory before it terminates, the memory becomes unavailable to
  182.   other programs until the system is restarted. Blocks may not be released
  183.   while they are locked. Function returns zero if the call was successful, or
  184.   a (xmsr) error code if the call has failed }
  185.  
  186. function XMS_MoveFromEMB(Handle : THandle; var Dest; Count : longint) : byte;
  187. { This function moves data from the extended memory to the conventional
  188.   memory. Handle is a handle number given by XMS_AllocEMB. Dest is a non-typed
  189.   variable so any kind of data can be written there. Count is the number of
  190.   bytes which should be moved. The state of the A20 line is preserved.
  191.   Function returns zero if the call was successful, or a (xmsr) error code
  192.   if the call has failed }
  193.  
  194. function XMS_MoveToEMB(Handle : THandle; var Source; Count : longint) : byte;
  195. { This function moves data from the conventional memory to the extended
  196.   memory. Handle is a handle number given by XMS_AllocEMB. Source is a
  197.   non-typed variable so any kind of data can be written there. Count is
  198.   the number of bytes which should be moved. The state of the A20 line is
  199.   preserved. Function returns zero if the call was successful, or a
  200.   (xmsr) error code if the call has failed }
  201.  
  202. function XMS_LockEMB(Handle : THandle) : pointer;
  203. { This function locks a specified EMB. This function is intended for use by
  204.   programs which enable the A20 line and access extended memory directly.
  205.   Handle is a handle number given by XMS_AllocEMB. The result is a 32-bit
  206.   linear address of the locked block or NIL if lock did not succeed. The
  207.   result value is stored in XMSResult variable }
  208.  
  209. function XMS_UnlockEMB(Handle : THandle) : byte;
  210. { This function unlocks previously locked blocks (by XMS_LockEMB). After
  211.   the EMB is unlocked the 32-bit pointer returned by XMS_LockEMB becomes
  212.   invalid and should not be used. Handle is a handle number given by
  213.   XMS_AllocEMB. The result value is zero if the call was successful,
  214.   otherwise it is one of the (xmsr) return codes }
  215.  
  216. function XMS_EMBHandlesAvail(Handle : THandle) : byte;
  217. { This function returns the number of free handles which are available to
  218.   your program. Handle is a handle number given by XMS_AllocEMB. The result
  219.   value is stored in XMSResult variable }
  220.  
  221. function XMS_EMBLockCount(Handle : THandle) : byte;
  222. { This function returns the lock count of a specified EMB. Handle is a handle
  223.   number given by XMS_AllocEMB. If the function returns zero it means that
  224.   the block is not locked. The result value is stored in XMSResult variable }
  225.  
  226. function XMS_EMBSize(Handle : THandle) : word;
  227. { This function determines the size of a specified EMB. Handle is a handle
  228.   number given by XMS_AllocEMB. The result is the size of the block in
  229.   kilo-bytes. The result code is stored in XMSResult variable }
  230.  
  231. function XMS_AllocUMB(Size : word) : longint;
  232. { This function allocates upper memory blocks (UMBs). Size is the size of
  233.   the block in paragraphs.
  234.   Function returns:
  235.     - segment base of the allocated block in the low-order word
  236.     - actual block size in paragraphs in the high-order word
  237.       In case of an error the high-order word will be the size of the largest
  238.       available block in paragraphs.
  239.   The result code is stored in XMSResult variable }
  240.  
  241. function XMS_FreeUMB(Segment : word) : byte;
  242. { This function releases the memory that was allocated by XMS_FreeUMB.
  243.   Segment must contain the segment base of the block which must be
  244.   released. The result value is zero if the call was successful, or
  245.   one of the (xmsr) error codes, otherwise }
  246.  
  247. function XMS_GetErrorMsg(ErrorCode : byte) : string;
  248. { This function translates the error code which is returned by all the
  249.   XMS_ functions in the unit from a number to a string. The error code is
  250.   written to the global variable XMSResult (byte). If XMSResult is equal
  251.   to zero then no errors were encountered. For more information about
  252.   the result codes, see (xmsr) constants in the unit's const section }
  253.  
  254.  
  255. (* CODE --------------------------------------------------------------------*)
  256.  
  257. implementation
  258.  
  259. type
  260.   TransferRec = record
  261.     TransferSize : longint;
  262.     SourceHandle : THandle;
  263.     SourceOffset : longint;
  264.     DestHandle : THandle;
  265.     DestOffset : longint
  266.   end;
  267.  
  268. var
  269.   XMSInitd : boolean;
  270.   XMSDriver : procedure;
  271.   TR : TransferRec; { Internal transfer EMB structure }
  272.  
  273. Function XMS_Setup; assembler;
  274. Asm
  275.   MOV [XMSInitd],False
  276.   MOV AX,4300h        { XMS Driver installation check }
  277.   INT 2Fh
  278.   CMP AL,80h
  279.   JE  @@1             { XMS found }
  280.   MOV AL,False        { else XMS manager not found }
  281.   JMP @@2
  282. @@1:
  283.   MOV AX,4310h        { Get address of XMS driver }
  284.   INT 2Fh
  285.   MOV WORD [XMSDriver],BX    { store offset }
  286.   MOV WORD [XMSDriver+2],ES  { store segment }
  287.   INC [XMSInitd]             { we have init'd our code }
  288.   MOV AL,True
  289. @@2:
  290. End; { XMS_Setup }
  291.  
  292. Function XMS_GetVersion; assembler;
  293. Asm
  294.   MOV [XMSResult],xmsrNotInitd
  295.   CMP [XMSInitd],True
  296.   JNE @@1
  297.   MOV AH,XGetVersion     { Function to get version }
  298.   CALL [XMSDriver]       { Call the XMS driver }
  299.   MOV [XMSResult],xmsrOk
  300.   CMP OfWhat,XMS         { XMS or XMM version? }
  301.   JE  @@1                { If XMS, it's already in AX }
  302.   MOV AX,BX              { If XMM, it's in BX, so move it to AX }
  303. @@1:
  304. End; { XMS_GetVersion }
  305.  
  306. Function XMS_HMAAvail; assembler;
  307. Asm
  308.   MOV [XMSResult],xmsrNotInitd
  309.   CMP [XMSInitd],True
  310.   JNE @@1
  311.   MOV AH,XGetVersion     { Function number }
  312.   CALL [XMSDriver]
  313.   MOV [XMSResult],xmsrOk
  314.   MOV AL,DL              { Store result value }
  315. @@1:
  316. End; { XMS_HMAAvail }
  317.  
  318. Function XMS_AllocHMA; assembler;
  319. Asm
  320.   MOV BL,xmsrNotInitd
  321.   CMP [XMSInitd],True
  322.   JNE @@1
  323.   MOV DX,Size         { Ammount of HMA wanted }
  324.   MOV AH,XRequestHMA  { Function to allocate HMA }
  325.   CALL [XMSDriver]    { Call the XMS driver }
  326.   OR  AX,AX
  327.   JZ  @@1
  328.   XOR BL,BL           { No error }
  329. @@1:
  330.   MOV AL,BL           { Store result value }
  331.   MOV [XMSResult],BL  { Save error code }
  332. End; { XMS_AllocHMA }
  333.  
  334. Function XMS_FreeHMA; assembler;
  335. Asm
  336.   MOV BL,xmsrNotInitd
  337.   CMP [XMSInitd],True
  338.   JNE @@1
  339.   MOV AH,XReleaseHMA  { Function to release HMA }
  340.   CALL [XMSDriver]    { Call the XMS driver }
  341.   OR  AX,AX
  342.   JZ  @@1             { If error then jump, else }
  343.   XOR BL,BL           { clear error code }
  344. @@1:
  345.   MOV AL,BL
  346.   MOV [XMSResult],BL  { Get return code in XMSResult }
  347. End; { XMS_FreeHMA }
  348.  
  349. Function XMS_GlobalEnableA20; assembler;
  350. Asm
  351.   MOV BL,xmsrNotInitd
  352.   CMP [XMSInitd],True
  353.   JNE @@1
  354.   MOV AH,XGlobalE20   { Function code }
  355.   CALL [XMSDriver]    { Call the XMS driver }
  356.   OR  AX,AX
  357.   JZ  @@1
  358.   XOR BL,BL           { Return no error }
  359. @@1:
  360.   MOV AL,BL
  361.   MOV [XMSResult],BL  { Store result value }
  362. End; { XMS_GlobalEnableA20 }
  363.  
  364. Function XMS_GlobalDisableA20; assembler;
  365. Asm
  366.   MOV BL,xmsrNotInitd
  367.   CMP [XMSInitd],True
  368.   JNE @@1
  369.   MOV AH,XGlobalD20   { Function code }
  370.   CALL [XMSDriver]    { Call the XMS driver }
  371.   OR  AX,AX
  372.   JZ  @@1
  373.   XOR BL,BL           { Return success }
  374. @@1:
  375.   MOV AL,BL
  376.   MOV [XMSResult],BL  { Store result value }
  377. End; { XMS_GlobalDisableA20 }
  378.  
  379. Function XMS_LocalEnableA20; assembler;
  380. Asm
  381.   MOV BL,xmsrNotInitd
  382.   CMP [XMSInitd],True
  383.   JNE @@1
  384.   MOV AH,XLocalE20    { Function code }
  385.   CALL [XMSDriver]    { Call the XMS driver }
  386.   OR  AX,AX
  387.   JZ  @@1
  388.   XOR BL,BL           { Return no error value }
  389. @@1:
  390.   MOV AL,BL
  391.   MOV [XMSResult],BL  { Store result value }
  392. End; { XMS_LocalEnableA20 }
  393.  
  394. Function XMS_LocalDisableA20; assembler;
  395. Asm
  396.   MOV BL,xmsrNotInitd
  397.   CMP [XMSInitd],True
  398.   JNE @@1
  399.   MOV AH,XLocalD20    { Function code }
  400.   CALL [XMSDriver]    { Call the XMS driver }
  401.   OR  AX,AX
  402.   JZ  @@1
  403.   XOR BL,BL           { Return no error }
  404. @@1:
  405.   MOV AL,BL
  406.   MOV [XMSResult],BL  { Save result }
  407. End; { XMS_LocalDisableA20 }
  408.  
  409. Function XMS_QueryA20; assembler;
  410. Asm
  411.   MOV BL,xmsrNotInitd
  412.   CMP [XMSInitd],True
  413.   JNE @@1
  414.   MOV AH,XQuery20     { Function code }
  415.   CALL [XMSDriver]    { Call the XMS driver; result in AL }
  416. @@1:
  417.   MOV [XMSResult],BL  { Store error code value }
  418. End; { XMS_QueryA20 }
  419.  
  420. Function XMS_MemAvail; assembler;
  421. Asm
  422.   MOV BL,xmsrNotInitd
  423.   CMP [XMSInitd],True
  424.   JNE @@1
  425.   MOV AH,XGetMemSize  { Function code }
  426.   CALL [XMSDriver]    { Call the XMS driver }
  427.   MOV AX,DX           { AX=Get XMS memory available in K-bytes }
  428. @@1:
  429.   MOV [XMSResult],BL  { Store result value }
  430. End; { XMS_MemAvail }
  431.  
  432. Function XMS_MaxAvail; assembler;
  433. Asm
  434.   MOV BL,xmsrNotInitd
  435.   CMP [XMSInitd],True
  436.   JNE @@1
  437.   MOV AH,XGetMemSize  { Function code }
  438.   CALL [XMSDriver]    { Call the XMS driver }
  439.                       { AX=Get XMS maximum memory block available in K-bytes }
  440. @@1:
  441.   MOV [XMSResult],BL  { Store result value }
  442. End; { XMS_MaxAvail }
  443.  
  444. Function XMS_AllocEMB; assembler;
  445. Asm
  446.   MOV BL,xmsrNotInitd
  447.   CMP [XMSInitd],True
  448.   JNE @@2
  449.   MOV AH,XAllocEMB    { Function code }
  450.   MOV DX,Size         { Number of K-Bytes to allocate }
  451.   CALL [XMSDriver]    { Call the XMS driver }
  452.   OR  AX,AX
  453.   JZ  @@1
  454.   MOV AX,DX           { Store handle number in AX }
  455.   XOR BL,BL           { Set no error }
  456.   JMP @@2
  457. @@1:
  458.   XOR AX,AX           { Return handle 0 if error }
  459. @@2:
  460.   MOV [XMSResult],BL
  461. End; { XMS_AllocEMB }
  462.  
  463. Function XMS_ReallocEMB; assembler;
  464. Asm
  465.   MOV BL,xmsrNotInitd
  466.   CMP [XMSInitd],True
  467.   JNE @@1
  468.   MOV AH,XReallocEMB  { Function code }
  469.   MOV DX,Handle       { Handle number }
  470.   MOV BX,Size         { New size wanted in K-Bytes }
  471.   CALL [XMSDriver]    { Call the XMS driver }
  472.   OR  AX,AX
  473.   JZ  @@1
  474.   XOR BL,BL           { There's no error }
  475. @@1:
  476.   MOV AL,BL           { Return result value }
  477.   MOV [XMSResult],BL  { Store error code }
  478. End; { XMS_ReallocEMB }
  479.  
  480. Function XMS_FreeEMB; assembler;
  481. Asm
  482.   MOV BL,xmsrNotInitd
  483.   CMP [XMSInitd],True
  484.   JNE @@1
  485.   MOV AH,XFreeEMB     { Function code }
  486.   MOV DX,Handle       { Set handle number in DX }
  487.   CALL [XMSDriver]    { Call the XMS driver }
  488.   OR  AX,AX
  489.   JZ  @@1
  490.   XOR BL,BL           { No error }
  491. @@1:
  492.   MOV AL,BL           { Return result value }
  493.   MOV [XMSResult],BL  { Store error code }
  494. End; { XMS_FreeEMB }
  495.  
  496. Function XMS_MoveFromEMB; assembler;
  497. Asm
  498.   PUSH DS
  499.   MOV BL,xmsrNotInitd
  500.   CMP [XMSInitd],True
  501.   JNE @@1
  502.   MOV CX,WORD PTR [Count]
  503.   MOV TR.WORD PTR [TransferSize],CX
  504.   MOV CX,WORD PTR [Count+2]
  505.   MOV TR.WORD PTR [TransferSize+2],CX
  506.   MOV CX,Handle
  507.   MOV TR.SourceHandle,CX
  508.   MOV WORD PTR [TR.SourceOffset],0
  509.   MOV WORD PTR [TR.SourceOffset+2],0
  510.   MOV TR.DestHandle,0
  511.   LES SI,Dest
  512.   MOV WORD PTR [TR.DestOffset],SI
  513.   MOV WORD PTR [TR.DestOffset+2],ES
  514.   MOV AH,XMoveEMB
  515.   MOV DX,SEG TR
  516.   MOV DS,DX
  517.   MOV SI,OFFSET TR
  518.   CALL [XMSDriver]
  519.   OR  AX,AX
  520.   JZ  @@1
  521.   XOR BL,BL
  522. @@1:
  523.   MOV AL,BL
  524.   MOV [XMSResult],BL
  525.   POP DS
  526. End; { XMS_MoveFromEMB }
  527.  
  528. Function XMS_MoveToEMB; assembler;
  529. Asm
  530.   PUSH DS
  531.   MOV BL,xmsrNotInitd
  532.   CMP [XMSInitd],True
  533.   JNE @@1
  534.   MOV CX,WORD PTR [Count]
  535.   MOV TR.WORD PTR [TransferSize],CX
  536.   MOV CX,WORD PTR [Count+2]
  537.   MOV TR.WORD PTR [TransferSize+2],CX
  538.   MOV TR.SourceHandle,0
  539.   LES SI,Source
  540.   MOV WORD PTR [TR.SourceOffset],SI
  541.   MOV WORD PTR [TR.SourceOffset+2],ES
  542.   MOV CX,Handle
  543.   MOV TR.DestHandle,CX
  544.   MOV WORD PTR [TR.DestOffset],0
  545.   MOV WORD PTR [TR.DestOffset+2],0
  546.   MOV AH,XMoveEMB
  547.   MOV DX,SEG TR
  548.   MOV DS,DX
  549.   MOV SI,OFFSET TR
  550.   CALL [XMSDriver]
  551.   OR  AX,AX
  552.   JZ  @@1
  553.   XOR BL,BL
  554. @@1:
  555.   MOV AL,BL
  556.   MOV [XMSResult],BL
  557.   POP DS
  558. End; { XMS_MoveToEMB }
  559.  
  560. Function XMS_LockEMB; assembler;
  561. Asm
  562.   CMP [XMSInitd],True
  563.   JNE @@1             { if not initialized, return the NIL pointer }
  564.   MOV AH,XLockEMB     { Function code }
  565.   MOV DX,Handle       { Handle in DX }
  566.   CALL [XMSDriver]    { Call the XMS driver }
  567.   OR  AX,AX           { Was the call successful? }
  568.   JNZ @@2             { Yep, so jump and return pointer }
  569. @@1:
  570.   XOR AX,AX
  571.   XOR DX,DX           { Return NIL }
  572.   MOV [XMSResult],xmsrLockFailed
  573.   JMP @@3
  574. @@2:
  575.   MOV AX,BX           { Offset in AX, Segment in DX }
  576.   MOV XMSResult,xmsrOk
  577. @@3:
  578. End; { XMS_LockEMB }
  579.  
  580. Function XMS_UnlockEMB; assembler;
  581. Asm
  582.   MOV BL,xmsrNotInitd
  583.   CMP [XMSInitd],True
  584.   JNE @@1
  585.   MOV AH,XUnlockEMB   { Function code }
  586.   MOV DX,Handle       { Handle in DX }
  587.   CALL [XMSDriver]    { Call the XMS driver }
  588.   OR  AX,AX
  589.   JZ  @@1
  590.   XOR BL,BL
  591. @@1:
  592.   MOV AL,BL
  593.   MOV [XMSResult],BL
  594. End; { XMS_UnlockEMB }
  595.  
  596. Function XMS_EMBHandlesAvail; assembler;
  597. Asm
  598.   MOV BL,xmsrNotInitd
  599.   CMP [XMSInitd],True
  600.   JNE @@1
  601.   MOV AH,XGetHandleInfo { Function code }
  602.   MOV DX,Handle
  603.   CALL [XMSDriver]
  604.   OR  AX,AX
  605.   JZ  @@1
  606.   MOV AL,BL             { Save number of free handles }
  607.   XOR BL,BL
  608. @@1:
  609.   MOV [XMSResult],BL
  610. End; { XMS_EMBHandlesAvail }
  611.  
  612. Function XMS_EMBLockCount; assembler;
  613. Asm
  614.   MOV BL,xmsrNotInitd
  615.   CMP [XMSInitd],True
  616.   JNE @@1
  617.   MOV AH,XGetHandleInfo
  618.   MOV DX,Handle         { Handle in DX }
  619.   CALL [XMSDriver]
  620.   OR  AX,AX
  621.   JZ  @@1
  622.   MOV AL,BH             { Save lock count }
  623.   XOR BL,BL
  624. @@1:
  625.   MOV [XMSResult],BL
  626. End; { XMS_EMBLockCount }
  627.  
  628. Function XMS_EMBSize; assembler;
  629. Asm
  630.   MOV BL,xmsrNotInitd
  631.   CMP [XMSInitd],True
  632.   JNE @@1
  633.   MOV AH,XGetHandleInfo
  634.   MOV DX,Handle
  635.   CALL [XMSDriver]
  636.   OR  AX,AX
  637.   JZ  @@1
  638.   MOV AX,DX             { Save EMB size in K-bytes }
  639.   XOR BL,BL
  640. @@1:
  641.   MOV [XMSResult],BL
  642. End; { XMS_EMBSize }
  643.  
  644. Function XMS_AllocUMB; assembler;
  645. Asm
  646.   MOV BL,xmsrNotInitd
  647.   CMP [XMSInitd],True
  648.   JNE @@1
  649.   MOV AH,XRequestUMB  { Function code }
  650.   MOV DX,Size         { Number of paragraphs we want }
  651.   CALL [XMSDriver]    { Call the XMS driver }
  652.   OR  AX,AX
  653.   JZ  @@1
  654.   MOV AX,BX           { Return segment of UMB in low-order word }
  655.                       { Actual block size in high-order word }
  656.   XOR BL,BL
  657. @@1:
  658.   MOV [XMSResult],BL
  659. End; { XMS_AllocUMB }
  660.  
  661. Function XMS_FreeUMB; assembler;
  662. Asm
  663.   MOV BL,xmsrNotInitd
  664.   CMP [XMSInitd],True
  665.   JNE @@1
  666.   MOV AH,XReleaseUMB  { Function code }
  667.   MOV DX,Segment      { Segment of UMB to release }
  668.   CALL [XMSDriver]    { Call the XMS driver }
  669.   OR  AX,AX
  670.   JZ  @@1
  671.   XOR BL,BL
  672. @@1:
  673.   MOV AL,BL
  674.   MOV [XMSResult],BL
  675. End; { XMS_FreeUMB }
  676.  
  677. Function XMS_GetErrorMsg;
  678. var S : ^String;
  679. Begin
  680.   GetMem(S, 128);
  681.   case ErrorCode of
  682.     xmsrNotInitd:      S^ := 'XMS driver not initialized';
  683.     xmsrBadFunction:   S^ := 'Function not implemented';
  684.     xmsrVDiskDetected: S^ := 'VDisk has detected';
  685.     xmsrA20Error:      S^ := 'An A20 error occurred';
  686.     xmsrDriverError:   S^ := 'A general driver error';
  687.     xmsrUnrecError:    S^ := 'Unrecoverable driver error';
  688.     xmsrNoHMA:         S^ := 'HMA does not exist';
  689.     xmsrHMAInUse:      S^ := 'HMA is already in use';
  690.     xmsrHMAMinError:   S^ := 'HMAMIN parameter is too large';
  691.     xmsrHMANotAlloc:   S^ := 'HMA is not allocated';
  692.     xmsrA20Enabled:    S^ := 'A20 line still enabled';
  693.     xmsrNoMoreMem:     S^ := 'All extended memory is allocated';
  694.     xmsrNoMoreHandles: S^ := 'All available XMS handles are allocated';
  695.     xmsrBadHandle:     S^ := 'Invalid block handle';
  696.     xmsrBadSourceH:    S^ := 'Block source handle is invalid';
  697.     xmsrBadSourceO:    S^ := 'Block source offset is invalid';
  698.     xmsrBadDestH:      S^ := 'Block destination handle is invalid';
  699.     xmsrBadDestO:      S^ := 'Block destination offset is invalid';
  700.     xmsrBadLength:     S^ := 'Block length is invalid';
  701.     xmsrBadOverlap:    S^ := 'Move operation has an invalid overlap';
  702.     xmsrParityError:   S^ := 'Parity error';
  703.     xmsrBlkNotLocked:  S^ := 'Block is not locked';
  704.     xmsrBlkLocked:     S^ := 'Block is locked';
  705.     xmsrBlkLCOverflow: S^ := 'Block lock count overflowed';
  706.     xmsrLockFailed:    S^ := 'Lock failed';
  707.     xmsrSmallerUMB:    S^ := 'Too large UMB requested';
  708.     xmsrNoUMB:         S^ := 'No UMB''s are available';
  709.     xmsrBadUMBSegment: S^ := 'UMB segment number is invalid';
  710.     else S^ := 'Unknown error'
  711.   end;
  712.   XMS_GetErrorMsg := S^;
  713.   FreeMem(S, 128)
  714. End; { XMS_GetErrorMsg }
  715.  
  716.  
  717. Begin
  718.   { Initialize global variables }
  719.   XMSInitd := False;
  720.   XMSResult := xmsrOk
  721. End. { XMSLib }